#pragma once

#include "Assisted.hpp"
#include "Abstract.hpp"
#include "DefinitionField.hpp"
#include "../tcp/source/Log.hpp"


namespace xu
{
    typedef std::pair<std::string, int> Address;

    // JSON
    class JsonMessage : public BaseMessage
    {
    public:
        using Ptr = std::shared_ptr<JsonMessage>;
        // 序列化
        virtual std::string Serialization() override
        {
            std::string body;
            bool ret = JSON::Serialization(_body, body);
            if (ret == false)
            {
                LOG(LogLevel::ERROR) << "Rpc请求序列化失败...";
                return std::string();
            }

            return body;
        }
        // 反序列化
        virtual bool Deserialization(const std::string &body) override
        {
            bool ret = JSON::Deserialization(body, _body);
            if (ret == false)
            {
                LOG(LogLevel::ERROR) << "Rpc请求反序列化失败...";
                return false;
            }

            return true;
        }

    protected:
        Json::Value _body;
    };

    class JsonRequest : public JsonMessage
    {
    public:
        using Ptr = std::shared_ptr<JsonRequest>;
    };

    class JsonResponse : public JsonMessage
    {
    public:
        using Ptr = std::shared_ptr<JsonResponse>;

        virtual bool Check() override
        {
            //检查KEY_RCODE字段是否存在和类型是否正确
            if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Rpc响应KEY_RCODE字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        virtual void SetRcode(const RCode &rcode)
        {
            _body[KEY_RCODE] = (int)rcode;
        }

        virtual RCode Rcode()
        {
            return (RCode)_body[KEY_RCODE].asInt();
        }
    };

    class RpcRequest : public JsonRequest
    {
    public:
        using Ptr = std::shared_ptr<RpcRequest>;
        virtual bool Check() override
        {
            // 检查KEY_METHOD字段是否存在
            if (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString())
            {
                LOG(LogLevel::ERROR) << "Rpc请求KEY_PARAMS字段不存在或者字段类型错误";
                return false;
            }

            //检查KEY_PARAMS字段是否存在 _body[KEY_PARAMS] ： 参数包
            if (_body[KEY_PARAMS].isNull() || !_body[KEY_PARAMS].isObject())
            {
                LOG(LogLevel::ERROR) << "Rpc请求KEY_PARAMS字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        void SetMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();
        }

        void SetParams(const Json::Value &params)
        {
            _body[KEY_PARAMS] = params;
        }

        Json::Value Params()
        {
            return _body[KEY_PARAMS];
        }
    };

    class TopicRequest : public JsonRequest
    {
    public:
        using Ptr = std::shared_ptr<TopicRequest>;
        virtual bool Check() override
        {
            // 检查KEY_TOPIC_KEY字段是否存在
            if (_body[KEY_TOPIC_KEY].isNull() || !_body[KEY_TOPIC_KEY].isString())
            {
                LOG(LogLevel::ERROR) << "Topic请求KEY_TOPIC_KEY字段不存在或者字段类型错误";
                return false;
            }

            // 检查KEY_OPTYPE字段是否存在
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Topic请求KEY_OPTYPE字段不存在或者字段类型错误";
                return false;
            }

            // 检查KEY_TOPIC_MSG字段是否存在 ->KEY_TOPIC_MSG存在的前提：_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH
            if ((_body[KEY_OPTYPE].asInt() == (int)TopicOptype::TOPIC_PUBLISH) &&
                (_body[KEY_TOPIC_MSG].isNull() || !_body[KEY_TOPIC_MSG].isString()))
            {
                LOG(LogLevel::ERROR) << "Topic请求KEY_TOPIC_MSG字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        void SetKey(const std::string &key)
        {
            _body[KEY_TOPIC_KEY] = key;
        }

        std::string Key()
        {
            return _body[KEY_TOPIC_KEY].asString();
        }

        void SetMsg(const std::string &msg)
        {
            _body[KEY_TOPIC_MSG] = msg;
        }

        std::string Msg()
        {
            return _body[KEY_TOPIC_MSG].asString();
        }

        // TopicOptype
        void SetOptype(const TopicOptype &optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        TopicOptype Optype()
        {
            return (TopicOptype)_body[KEY_OPTYPE].asInt();
        }
    };

    class ServiceRequest : public JsonRequest
    {
    public:
        using Ptr = std::shared_ptr<ServiceRequest>;
        virtual bool Check() override
        {
            // 检查KEY_OPTYPE字段是否存在
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Service请求KEY_OPTYPE字段不存在或者字段类型错误";
                return false;
            }

            // 检查KEY_METHOD字段是否存在
            if ((_body[KEY_OPTYPE].asInt() != (int)ServiceOptype::SERVICE_OVERLOAD) && (_body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString()))
            {
                LOG(LogLevel::ERROR) << "Service请求KEY_METHOD字段不存在或者字段类型错误";
                return false;
            }

            if((_body[KEY_OPTYPE].asInt() == (int)ServiceOptype::SERVICE_OVERLOAD) && (_body[KEY_OVERLOAD].isNull()
             || !_body[KEY_OVERLOAD].isBool() ))
             {
                LOG(LogLevel::ERROR) << "Service请求KEY_OVERLOAD字段不存在或者字段类型错误";
                return false;
             }

            //  检查KEY_HOST字段是否存在，KEY_HOST字段存在的前提：_body[KEY_OPTYPE].asInt() != (int)ServiceOptype::SERVICE_DISCOVERY
            if ((_body[KEY_OPTYPE].asInt() != (int)ServiceOptype::SERVICE_DISCOVERY) &&
                ((_body[KEY_HOST].isNull() || !_body[KEY_HOST].isObject()) ||
                 _body[KEY_HOST][KEY_HOST_IP].isNull() || !_body[KEY_HOST][KEY_HOST_IP].isString() ||
                 _body[KEY_HOST][KEY_HOST_PORT].isNull() || !_body[KEY_HOST][KEY_HOST_PORT].isInt()))
            {
                LOG(LogLevel::ERROR) << "Service请求KEY_HOST字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        void SetOverload(const bool& overload)
        {
            _body[KEY_OVERLOAD] = overload;
        }

        bool Overload()
        {
            return _body[KEY_OVERLOAD].asBool();
        } 

        void SetMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();
        }

        void SetHost(const Address &host)
        {
            Json::Value val;
            val[KEY_HOST_IP] = host.first;
            val[KEY_HOST_PORT] = host.second;
            _body[KEY_HOST] = val;
        }

        Address Host()
        {
            Address addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }

        // TopicOptype
        void SetOptype(const ServiceOptype &optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        ServiceOptype Optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }
    };

    class RpcResponse : public JsonResponse
    {
    public:
        using Ptr = std::shared_ptr<RpcResponse>;
        virtual bool Check() override
        {
            // 检查KEY_RCODE字段是否存在
            if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Rpc响应KEY_RCODE字段不存在或者字段类型错误";
                return false;
            }

            // 检查KEY_RESULT字段是否存在
            if (_body[KEY_RESULT].isNull())
            {
                LOG(LogLevel::ERROR) << "Rpc响应KEY_RESULT字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        void SetResult(const Json::Value &res)
        {
            _body[KEY_RESULT] = res;
        }

        Json::Value Result()
        {
            return _body[KEY_RESULT];
        }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using Ptr = std::shared_ptr<TopicResponse>;
    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using Ptr = std::shared_ptr<ServiceResponse>;
        virtual bool Check() override
        {
            // 检查KEY_RCODE字段是否存在
            if (_body[KEY_RCODE].isNull() || !_body[KEY_RCODE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Service响应KEY_RCODE字段不存在或者字段类型错误";
                return false;
            }

           // 检查KEY_OPTYPE字段是否存在
            if (_body[KEY_OPTYPE].isNull() || !_body[KEY_OPTYPE].isIntegral())
            {
                LOG(LogLevel::ERROR) << "Service响应KEY_OPTYPE字段不存在或者字段类型错误";
                return false;
            }

            // 检查KEY_HOST字段是否存在，KEY_HOST存在的前提：_body[KEY_OPTYPE].asInt() == (int)ServiceOptype::SERVICE_DISCOVERY
            if (_body[KEY_OPTYPE].asInt() == (int)ServiceOptype::SERVICE_DISCOVERY && (_body[KEY_HOST].isNull() || !_body[KEY_HOST].isArray() || _body[KEY_METHOD].isNull() || !_body[KEY_METHOD].isString()))
            {
                LOG(LogLevel::ERROR) << "Service响应KEY_HOST字段不存在或者字段类型错误";
                return false;
            }

            return true;
        }

        void SetMethod(const std::string &method)
        {
            _body[KEY_METHOD] = method;
        }

        std::string Method()
        {
            return _body[KEY_METHOD].asString();
        }

        // TopicOptype
        void SetOptype(const ServiceOptype &optype)
        {
            _body[KEY_OPTYPE] = (int)optype;
        }

        ServiceOptype Optype()
        {
            return (ServiceOptype)_body[KEY_OPTYPE].asInt();
        }

        void SetHost(const std::vector<Address> &host)
        {
            for (auto &e : host)
            {
                Json::Value val;
                val[KEY_HOST_IP] = e.first;
                val[KEY_HOST_PORT] = e.second;
                _body[KEY_HOST].append(val);
            }
        }

        std::vector<Address> Host()
        {
            std::vector<Address> ret;
            for (int i = 0; i < _body[KEY_HOST].size(); ++i)
            {
                Address addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                ret.push_back(addr);
            }
            return ret;
        }
    };

    //实现一个消息对象的生产工厂
    class MessageFactory
    {
    public:
    static BaseMessage::Ptr create(MType mtype)
    {
        switch (mtype)
        {
        case MType::REQ_RPC : return std::make_shared<RpcRequest>();
        case MType::RSP_RPC : return std::make_shared<RpcResponse>();   
        case MType::REQ_TOPIC : return std::make_shared<TopicRequest>();
        case MType::RSP_TOPIC : return std::make_shared<TopicResponse>();
        case MType::REQ_SERVICE : return std::make_shared<ServiceRequest>();
        case MType::RSP_SERVICE : return std::make_shared<ServiceResponse>();
        default: return nullptr;
        }
    }

    template<typename T,typename... Args>
    static std::shared_ptr<T> create(Args &&...args)
    {
        return std::make_shared<T>(std::forward<Args>(args)...);
    }
    };
};